#include "AsciiSceneExportParser.h"

ASEParser::ASEParser() : TextParser()
{
	CallbackMap g_always, g_map, matlist_map, mat_map, geom_map, mesh_map, vertex_map, index_map, normal_map, tvert_map, tface_map;
	g_always["{"] = (void(*)(ParserStack*))&STACK_BEGIN;
	g_always["}"] = (void(*)(ParserStack*))&STACK_END;
	
	g_map["*GEOMOBJECT"] = (void(*)(ParserStack*))(&GEOMOBJECT);
	g_map["*COMMENT"] = (void(*)(ParserStack*))&COMMENT;
	g_map["*MATERIAL_LIST"] = (void(*)(ParserStack*))&MATERIAL_LIST;

	matlist_map["*MATERIAL_COUNT"] = (void(*)(ParserStack*))&MATERIAL_COUNT;
	matlist_map["*MATERIAL"] = (void(*)(ParserStack*))&MATERIAL;

	mat_map["*MATERIAL_NAME"] = (void(*)(ParserStack*))&MATERIAL_NAME;
	mat_map["*MATERIAL_AMBIENT"] = (void(*)(ParserStack*))&MATERIAL_AMBIENT;
	mat_map["*MATERIAL_DIFFUSE"] = (void(*)(ParserStack*))&MATERIAL_DIFFUSE;
	mat_map["*MATERIAL_SPECULAR"] = (void(*)(ParserStack*))&MATERIAL_SPECULAR;
	mat_map["*MATERIAL_SHINE"] = (void(*)(ParserStack*))&MATERIAL_SPECULARPOWER;

	geom_map["*MESH"] =  (void(*)(ParserStack*))&MESH;
	geom_map["*NODE_NAME"] = (void(*)(ParserStack*))&NODE_NAME;
	geom_map["*NODE_TM"] = (void(*)(ParserStack*))&NODE_TM;

	mesh_map["*MESH_NUMVERTEX"] = (void(*)(ParserStack*))&MESH_NUMVERTEX;
	mesh_map["*MESH_NUMFACES"] = (void(*)(ParserStack*))&MESH_NUMFACES;
	mesh_map["*MESH_VERTEX_LIST"] = (void(*)(ParserStack*))&MESH_VERTEX_LIST;
	mesh_map["*MESH_FACE_LIST"] = (void(*)(ParserStack*))&MESH_FACE_LIST;
	mesh_map["*MESH_NUMTVERTEX"] = (void(*)(ParserStack*))&MESH_NUMTVERTEX;
	mesh_map["*MESH_TVERTLIST"] = (void(*)(ParserStack*))&MESH_TVERTLIST;
	mesh_map["*MESH_TFACELIST"] = (void(*)(ParserStack*))&MESH_TFACELIST;
	mesh_map["*MESH_NORMALS"] = (void(*)(ParserStack*))&MESH_NORMALS;

	vertex_map["*MESH_VERTEX"] = (void(*)(ParserStack*))&MESH_VERTEX;

	index_map["*MESH_FACE"] = (void(*)(ParserStack*))&MESH_FACE;

	tvert_map["*MESH_TVERT"] = (void(*)(ParserStack*))&MESH_TVERT;

	tface_map["*MESH_TFACE"] = (void(*)(ParserStack*))&MESH_TFACE;

	normal_map["*MESH_FACENORMAL"] = (void(*)(ParserStack*))&MESH_FACENORMAL;

	Stack.m_StackMap[-2] = g_always; // always is -2
	Stack.m_StackMap[-1] = g_map; // global is always -1
	Stack.m_StackMap[0] = geom_map;
	Stack.m_StackMap[1] = mesh_map;
	Stack.m_StackMap[2] = vertex_map;
	Stack.m_StackMap[3] = index_map;
	Stack.m_StackMap[4] = normal_map;
	Stack.m_StackMap[5] = tvert_map;
	Stack.m_StackMap[6] = tface_map;
	Stack.m_StackMap[7] = matlist_map;
	Stack.m_StackMap[8] = mat_map;
}
ASEParser::~ASEParser()
{
}

void ASEParser::VBegin()
{
	m_AssetDataList.clear();
	Stack.m_ToStack = -1;
}
void ASEParser::VEnd()
{
	AssetDataList::iterator i = m_AssetDataList.begin();
	AssetDataList::iterator end = m_AssetDataList.end();
	AssetDataPtr a;
	while(i != end)
	{
		a = (*i);
		a->Restore();
		a->RestoreChildren();
		++i;
	}
	m_TempMap.clear();
}
void ASEParser::GEOMOBJECT(ASEParser *instance)
{
	instance->Stack.m_ToStack = 0;
	instance->m_AssetDataList.push_back(AssetDataPtr(RE_NEW RE_Mesh));
	instance->m_pAssetData = instance->m_AssetDataList.back();
}
void ASEParser::COMMENT(ASEParser *instance)
{
	char buffer[64];
	instance->ParseNext(buffer);
}
void ASEParser::NODE_NAME(ASEParser *instance)
{
	char buffer[24];
	instance->ParseNext( buffer );
	RE_Mesh * mesh = static_cast<RE_Mesh *>(instance->m_pAssetData.get());
	std::string a = buffer;
	mesh->m_name = RE_String(a.substr(1,a.length() - 2));
}
void ASEParser::NODE_TM(ASEParser *instance)
{
	instance->Stack.m_ToStack = 10;
}
void ASEParser::MESH(ASEParser *instance)
{
	instance->Stack.m_ToStack = 1;
}
void ASEParser::MESH_NUMVERTEX(ASEParser *instance)
{
	char buffer[12];
	instance->ParseNext(buffer); // get uniq vertex count
	instance->m_TempMap.resize(atoi(buffer));
}
void ASEParser::MESH_NUMFACES(ASEParser *instance)
{
	char buffer[12];
	instance->ParseNext(buffer); // get face count
	RE_Mesh * mesh = static_cast<RE_Mesh *>(instance->m_pAssetData.get());
	mesh->m_Vertices.resize(atoi(buffer) * 3);
}
void ASEParser::MESH_VERTEX_LIST(ASEParser *instance)
{
	instance->Stack.m_ToStack = 2;
}
void ASEParser::MESH_VERTEX(ASEParser *instance)
{
	char buffer[16];
	instance->ParseNext(buffer); // get vertex id
	int i = atoi(buffer);
	instance->ParseNext(buffer); // get X axis
	instance->m_TempMap[i].x = atof(buffer);
	instance->ParseNext(buffer); // get Y axis
	instance->m_TempMap[i].z = atof(buffer);
	instance->ParseNext(buffer); // get Z axis
	instance->m_TempMap[i].y = atof(buffer);
}
void ASEParser::MESH_FACE_LIST(ASEParser *instance)
{
	instance->Stack.m_ToStack = 3;
}
void ASEParser::MESH_FACE(ASEParser *instance)
{
	char buffer[16];
	RE_Mesh * mesh = static_cast<RE_Mesh *>(instance->m_pAssetData.get());
	instance->ParseNext( buffer );
	//find the : and remove it
	int i = 0;
	while(buffer[i] != ':')
	{
		++i;
	}
	buffer[i] = '\0';
	i = atoi(buffer); // aquire the face id
	instance->ParseNext();
	instance->ParseNext( buffer );
	mesh->m_Vertices[i * 3].Position = instance->m_TempMap[atoi(buffer)];
	instance->ParseNext();
	instance->ParseNext( buffer );
	mesh->m_Vertices[i * 3 + 1].Position = instance->m_TempMap[atoi(buffer)];
	instance->ParseNext();
	instance->ParseNext( buffer );
	mesh->m_Vertices[i * 3 + 2].Position = instance->m_TempMap[atoi(buffer)];
}

void ASEParser::MESH_NORMALS(ASEParser *instance)
{
	instance->Stack.m_ToStack = 4;
}

void ASEParser::MESH_FACENORMAL(ASEParser *instance)
{
	char buffer[12];
	RE_Mesh * mesh = static_cast<RE_Mesh *>(instance->m_pAssetData.get());
	instance->ParseNext(buffer);
	unsigned int i = atoi(buffer);
	instance->ParseNext();
	instance->ParseNext();
	instance->ParseNext(); //skip the x,y,z of face normal, I don't care bout it
	for(int u = 0; u < 3; u++) // for each face -> there are 3 verteces
	{
		instance->ParseNext(); //now skip *MESH_FACENORMAL
		instance->ParseNext(); //now skip the vertex id. It is not needed. They are ordered here.
		instance->ParseNext(buffer); // now take X of the fist vert
		mesh->m_Vertices[i * 3 + u].Normal.x = atof(buffer);
		instance->ParseNext(buffer);
		mesh->m_Vertices[i * 3 + u].Normal.y = atof(buffer);
		instance->ParseNext(buffer);
		mesh->m_Vertices[i * 3 + u].Normal.z = atof(buffer);
	}
}

void ASEParser::MESH_NUMTVERTEX(ASEParser *instance)
{
	char buffer[12];
	instance->ParseNext(buffer);
	instance->m_TempMap.resize(atoi(buffer));
}
void ASEParser::MESH_TVERTLIST(ASEParser *instance)
{
	instance->Stack.m_ToStack = 5;
}
void ASEParser::MESH_TVERT(ASEParser *instance)
{
	char buffer[12];
	RE_Mesh * mesh = static_cast<RE_Mesh *>(instance->m_pAssetData.get());
	instance->ParseNext(buffer);
	unsigned int i = atoi(buffer);
	instance->ParseNext(buffer);
	instance->m_TempMap[i].x = atof(buffer);
	instance->ParseNext(buffer);
	instance->m_TempMap[i].y = atof(buffer);
	instance->ParseNext();
}

void ASEParser::MESH_TFACELIST(ASEParser *instance)
{
	instance->Stack.m_ToStack = 6;
}

void ASEParser::MESH_TFACE(ASEParser *instance)
{
	char buffer[12];
	RE_Mesh * mesh = static_cast<RE_Mesh *>(instance->m_pAssetData.get());
	instance->ParseNext(buffer);
	unsigned int i = atoi(buffer), u = 0;
	for(char a = 0; a < 3; a++)
	{
		instance->ParseNext(buffer); u = atoi(buffer);
		mesh->m_Vertices[i * 3 + a].TexCoord.x = instance->m_TempMap[u].x;
		mesh->m_Vertices[i * 3 + a].TexCoord.y = instance->m_TempMap[u].y;
	}
}
void ASEParser::MATERIAL_LIST(ASEParser *instance)
{
	instance->Stack.m_ToStack = 7;
}

void ASEParser::MATERIAL_COUNT(ASEParser *instance)
{
	instance->ParseNext(); //I don't care bout this. I'm not using array..
}

void ASEParser::MATERIAL(ASEParser *instance)
{
	instance->Stack.m_ToStack = 8;
	//allocate RE_NEW material slot
	instance->m_AssetDataList.push_back(AssetDataPtr(RE_NEW RE_Material));
	//set is as working asset
	instance->m_pAssetData = instance->m_AssetDataList.back();
}

void ASEParser::MATERIAL_NAME(ASEParser *instance)
{
	char buffer[36];
	instance->ParseNext(buffer);
	RE_Material * mat = dynamic_cast<RE_Material *>(instance->m_pAssetData.get());
	mat->m_name = RE_String(buffer);
}

void ASEParser::MATERIAL_AMBIENT(ASEParser *instance)
{
	char buffer[12];
	RE_Material * mat = dynamic_cast<RE_Material *>(instance->m_pAssetData.get());
	instance->ParseNext(buffer);
	mat->m_Ambient.w = 1.0f;
	mat->m_Ambient.x = atof(buffer);
	instance->ParseNext(buffer);
	mat->m_Ambient.y = atof(buffer);
	instance->ParseNext(buffer);
	mat->m_Ambient.z = atof(buffer);
}

void ASEParser::MATERIAL_DIFFUSE(ASEParser *instance)
{
	char buffer[12];
	RE_Material * mat = dynamic_cast<RE_Material *>(instance->m_pAssetData.get());
	instance->ParseNext(buffer);
	mat->m_Diffuse.w = 1.0f;
	mat->m_Diffuse.x = atof(buffer);
	instance->ParseNext(buffer);
	mat->m_Diffuse.y = atof(buffer);
	instance->ParseNext(buffer);
	mat->m_Diffuse.z = atof(buffer);
}

void ASEParser::MATERIAL_SPECULAR(ASEParser *instance)
{
	char buffer[12];
	RE_Material * mat = dynamic_cast<RE_Material *>(instance->m_pAssetData.get());
	instance->ParseNext(buffer);
	mat->m_Specular.w = 1.0f;
	mat->m_Specular.x = atof(buffer);
	instance->ParseNext(buffer);
	mat->m_Specular.y = atof(buffer);
	instance->ParseNext(buffer);
	mat->m_Specular.z = atof(buffer);
}

void ASEParser::MATERIAL_SPECULARPOWER(ASEParser *instance)
{
	char buffer[12];
	RE_Material * mat = dynamic_cast<RE_Material *>(instance->m_pAssetData.get());
	instance->ParseNext(buffer);
	mat->m_SpecularPower = atof(buffer);
}

void ASEParser::STACK_BEGIN(ASEParser *instance)
{
	instance->Stack.m_Stack.push_back(instance->Stack.m_ToStack);// m_ToStack. We always have RE_NEW stack level when it need, even if it is not impl.
	//however this help to match begin with ends.
}
void ASEParser::STACK_END(ASEParser *instance)
{
	instance->Stack.m_Stack.pop_back();
}